package auth

import (
	"strings"

	"gitee.com/go-course/go9/projects/devcloud/mcenter/apps/endpoint"
	"gitee.com/go-course/go9/projects/devcloud/mcenter/apps/permission"
	"gitee.com/go-course/go9/projects/devcloud/mcenter/apps/token"
	"gitee.com/go-course/go9/projects/devcloud/mcenter/client/rpc"
	"gitee.com/go-course/go9/projects/devcloud/mcenter/common/logger"
	"github.com/emicklei/go-restful/v3"
	"github.com/infraboard/mcube/exception"
	"github.com/infraboard/mcube/http/restful/response"
)

func NewHttpAuther(client *rpc.ClientSet) *httpAuther {
	return &httpAuther{
		client: client,
	}
}

type httpAuther struct {
	client *rpc.ClientSet
}

// FilterFunction definitions must call ProcessFilter on the FilterChain to pass on the control and eventually call the RouteFunction
func (a *httpAuther) AuthFunc(
	req *restful.Request,
	resp *restful.Response,
	next *restful.FilterChain) {
	logger.L().Info().Msgf("%s", req)
	// 请求拦截并处理
	// 检查Token令牌 如果不合法 Authorization: breaer xxxx

	// 权限判断, 用户当前访问了那个接口()
	accessRoute := req.SelectedRoute()
	ep := &endpoint.Endpoint{
		Spec: &endpoint.CreateEndpointRequest{
			// 自己想办法补充, 生成service client client_id = service_id
			// 自己掉rpc 查询自己的service id已经service的而其配置
			ServiceId: "cfsrgnh3n7pi7u2is87g",
			Method:    accessRoute.Method(),
			Path:      accessRoute.Path(),
			Operation: accessRoute.Operation(),
		},
	}

	// 补充Meta信息
	isAuth := accessRoute.Metadata()["auth"]
	if isAuth != nil {
		ep.Spec.Auth = isAuth.(bool)
	}
	isPerm := accessRoute.Metadata()["perm"]
	if isPerm != nil {
		ep.Spec.Perm = isPerm.(bool)
	}

	// 开启了认证
	if ep.Spec.Auth {
		// 从Header中获取token
		authHeader := req.HeaderParameter(token.TOKEN_HEADER_KEY)
		tkl := strings.Split(authHeader, " ")
		if len(tkl) != 2 {
			response.Failed(resp, exception.NewUnauthorized("令牌不合法, 格式： Authorization: breaer xxxx"))
			return
		}

		tk := tkl[1]
		logger.L().Debug().Msgf("get token: %s", tk)

		// 检查Token的合法性, 需要通过RPC进行检查
		tkObj, err := a.client.Token().ValidateToken(
			req.Request.Context(),
			token.NewValidateTokenRequest(tk),
		)
		if err != nil {
			response.Failed(resp, exception.NewUnauthorized("令牌校验不合法, %s", err))
			return
		}

		// 放入上下文
		req.SetAttribute(token.ATTRIBUTE_TOKEN_KEY, tkObj)

		// 只有用户认证了才能进行鉴权
		if ep.Spec.Perm {
			checkReq := permission.NewCheckPermissionRequest()
			checkReq.UserId = tkObj.UserId
			checkReq.Namespace = tkObj.Namespace
			checkReq.ServiceId = ep.Spec.ServiceId
			checkReq.HttpMethod = ep.Spec.Method
			checkReq.HttpPath = ep.Spec.Path
			checkResp, err := a.client.Permission().CheckPermission(
				req.Request.Context(),
				checkReq,
			)
			if err != nil {
				response.Failed(resp, exception.NewPermissionDeny("权限校验失败, %s", err))
				return
			}
			if !checkResp.HasPermisson {
				response.Failed(resp, exception.NewPermissionDeny("权限校验失败"))
				return
			}
		}
	}

	// 交给下个处理
	next.ProcessFilter(req, resp)
}
